package com.starsoft.quant.strategy.index;

import java.util.Collections;
import java.util.Date;
import java.util.List;

import com.starsoft.frame.util.DateUtil;
import com.starsoft.smdc.bean.SmdcMarketDaily;

public class IndexCaculator {

	private static final int MAX_DATE_DIFF = 40;
	
	public static List<SmdcMarketDaily> valuationCaculate(List<SmdcMarketDaily> markets){
		if(markets==null||markets.isEmpty()){
			return markets;
		}
		checkInputSecId(markets);
		sortByDate(markets);
		
		SmdcMarketDaily lastHas = null;
		for (SmdcMarketDaily market : markets) {
			if (market.getPeWeighted() != null&&market.getPbWeighted() != null&&market.getRoeWeighted() != null&&market.getDiviWeighted() != null) {
				lastHas = market;
			} else if (lastHas != null) {
				double fator = market.getClosePrice() / lastHas.getClosePrice();
				market.setPeWeighted(lastHas.getPeWeighted() * fator);
				market.setPbWeighted(lastHas.getPbWeighted() * fator);
				market.setRoeWeighted(lastHas.getRoeWeighted());
				market.setDiviWeighted(lastHas.getDiviWeighted() / fator);
				market.setDivi(lastHas.getDivi() * fator);
			}
		}
		return markets;
	}

	public static Double percentitle(List<Double> values, Double target) {
		if (target == null) {
			return null;
		}
		int nullCnt = 0;
		int biggerCnt = 0;
		for (Double value : values) {
			if (value == null) {
				nullCnt++;
				continue;
			}
			if (value >= target) {
				biggerCnt++;
			}
		}
		if (nullCnt * 1.0 / values.size() > 0.1) {
			return null;
		} else {
			return 1-biggerCnt * 1.0 / (values.size() - nullCnt);
		}
	}

	public static Double[] getIncome(List<SmdcMarketDaily> markets) {
		Double beginPe = markets.get(0).getPeWeighted();
		Double endPe= markets.get(markets.size()-1).getPeWeighted();
		Double beginPb = markets.get(0).getPbWeighted();
		Double endPb= markets.get(markets.size()-1).getPbWeighted();
		double beginPrice = markets.get(0).getClosePrice();
		double endPrice = markets.get(markets.size()-1).getClosePrice();
		Date beginDate = markets.get(0).getId().getTradeDate();
		Date endDate = markets.get(markets.size()-1).getId().getTradeDate();
		double years = DateUtil.getYears(beginDate, endDate);
		
		Double incomeYearly = Math.pow(endPrice / beginPrice, 1 / years) - 1;
		Double fullIncomeYearly = null, peIncomeYearly = null, pbIncomeYearly = null;
		
		if (markets.get(markets.size() - 1).getDivi() != null && markets.get(0).getDivi() != null) {
			double fullIncome = markets.get(markets.size() - 1).getDivi() / markets.get(0).getDivi();
			fullIncomeYearly = Math.pow(fullIncome, 1 / years) - 1;
		}
		if(beginPe!=null && endPe!=null) {
			peIncomeYearly = (fullIncomeYearly==null?incomeYearly:incomeYearly) + (Math.pow(beginPe / endPe, 1 / years) - 1);
			pbIncomeYearly = (fullIncomeYearly==null?incomeYearly:incomeYearly) + (Math.pow(beginPb / endPb, 1 / years) - 1);
		}

		return new Double[]{fullIncomeYearly, peIncomeYearly, incomeYearly, pbIncomeYearly};
	}
	
	public static double priceChangeNDay(List<SmdcMarketDaily> markets, int days) {
		int index = markets.size() - 1;
		double beginPrice = markets.get(index - days).getClosePrice();
		double endPrice = markets.get(index).getClosePrice();
		return endPrice / beginPrice - 1;
	}
	
	public static Double priceChangeNatualDay(List<SmdcMarketDaily> markets, Date beginDate) {
		SmdcMarketDaily beginMarket = null;
		for (SmdcMarketDaily market : markets) {
			if(market.getId().getTradeDate().compareTo(beginDate)<=0) {
				beginMarket = market;
			}
		}
		if(beginMarket == null) return null;
		SmdcMarketDaily endMarket = markets.get(markets.size() - 1);
		if(beginMarket.getDivi()!=null && endMarket.getDivi()!=null) {
			return endMarket.getDivi()/beginMarket.getDivi()-1;
		} else {
			return endMarket.getClosePrice()/beginMarket.getClosePrice()-1;
		}
	}
	
	private static boolean checkInputSecId(List<SmdcMarketDaily> markets) {
		String secIdToCheck = markets.get(0).getId().getSecId();
		for (SmdcMarketDaily market : markets) {
			String secId = market.getId().getSecId();
			if (!secId.equals(secIdToCheck)) {
				return false;
			}
		}
		return true;
	}

	private static void sortByDate(List<SmdcMarketDaily> markets) {
		Collections.sort(markets, (o1, o2) -> {
			Date date1 = o1.getId().getTradeDate();
			Date date2 = o2.getId().getTradeDate();
			if (date1.before(date2)) {
				return -1;
			} else if (date1.after(date2)) {
				return 1;
			} else {
				return 0;
			}
		});
	}

	
}
